{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "scrolled": false
   },
   "source": [
    "# 副本与视图\n",
    "在 Numpy 中，尤其是在做数组运算或数组操作时，返回结果不是数组的 **副本** 就是 **视图**。\n",
    "\n",
    "在 Numpy 中，所有赋值运算不会为数组和数组中的任何元素创建副本。\n",
    "\n",
    "\n",
    "- `numpy.ndarray.copy()` 函数创建一个副本。 对副本数据进行修改，不会影响到原始数据，它们物理内存不在同一位置。\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "y = x\n",
    "y[0] = -1\n",
    "print(x)\n",
    "# [-1  2  3  4  5  6  7  8]\n",
    "print(y)\n",
    "# [-1  2  3  4  5  6  7  8]\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "y = x.copy()\n",
    "y[0] = -1\n",
    "print(x)\n",
    "# [1 2 3 4 5 6 7 8]\n",
    "print(y)\n",
    "# [-1  2  3  4  5  6  7  8]\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "【例】数组切片操作返回的对象只是原数组的视图。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "y = x\n",
    "y[::2, :3:2] = -1\n",
    "print(x)\n",
    "# [[-1 12 -1 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [-1 22 -1 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [-1 32 -1 34 35]]\n",
    "print(y)\n",
    "# [[-1 12 -1 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [-1 22 -1 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [-1 32 -1 34 35]]\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "y = x.copy()\n",
    "y[::2, :3:2] = -1\n",
    "print(x)\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "print(y)\n",
    "# [[-1 12 -1 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [-1 22 -1 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [-1 32 -1 34 35]]\n",
    "```\n",
    "\n",
    "\n",
    "# 索引与切片\n",
    "\n",
    "数组索引机制指的是用方括号（[]）加序号的形式引用单个数组元素，它的用处很多，比如抽取元素，选取数组的几个元素，甚至为其赋一个新值。\n",
    "\n",
    "## 整数索引\n",
    "\n",
    "【例】要获取数组的单个元素，指定元素的索引即可。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "print(x[2])  # 3\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "print(x[2])  # [21 22 23 24 25]\n",
    "print(x[2][1])  # 22\n",
    "print(x[2, 1])  # 22\n",
    "```\n",
    "\n",
    "## 切片索引\n",
    "\n",
    "切片操作是指抽取数组的一部分元素生成新数组。对 python **列表**进行切片操作得到的数组是原数组的**副本**，而对 **Numpy** 数据进行切片操作得到的数组则是指向相同缓冲区的**视图**。\n",
    "\n",
    "\n",
    "如果想抽取（或查看）数组的一部分，必须使用切片语法，也就是，把几个用冒号（ `start:stop:step` ）隔开的数字置于方括号内。\n",
    "\n",
    "为了更好地理解切片语法，还应该了解不明确指明起始和结束位置的情况。如省去第一个数字，numpy 会认为第一个数字是0；如省去第二个数字，numpy 则会认为第二个数字是数组的最大索引值；如省去最后一个数字，它将会被理解为1，也就是抽取所有元素而不再考虑间隔。\n",
    "\n",
    "\n",
    "【例】对一维数组的切片\n",
    "\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "print(x[0:2])  # [1 2]\n",
    "#用下标0~5,以2为步长选取数组\n",
    "print(x[1:5:2])  # [2 4]\n",
    "print(x[2:])  # [3 4 5 6 7 8]\n",
    "print(x[:2])  # [1 2]\n",
    "print(x[-2:])  # [7 8]\n",
    "print(x[:-2])  # [1 2 3 4 5 6]\n",
    "print(x[:])  # [1 2 3 4 5 6 7 8]\n",
    "#利用负数下标翻转数组\n",
    "print(x[::-1])  # [8 7 6 5 4 3 2 1]\n",
    "```\n",
    "\n",
    "【例】对二维数组切片\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "print(x[0:2])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]]\n",
    "\n",
    "print(x[1:5:2])\n",
    "# [[16 17 18 19 20]\n",
    "#  [26 27 28 29 30]]\n",
    "\n",
    "print(x[2:])\n",
    "# [[21 22 23 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "print(x[:2])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]]\n",
    "\n",
    "print(x[-2:])\n",
    "# [[26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "print(x[:-2])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]]\n",
    "\n",
    "print(x[:])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "print(x[2, :])  # [21 22 23 24 25]\n",
    "print(x[:, 2])  # [13 18 23 28 33]\n",
    "print(x[0, 1:4])  # [12 13 14]\n",
    "print(x[1:4, 0])  # [16 21 26]\n",
    "print(x[1:3, 2:4])\n",
    "# [[18 19]\n",
    "#  [23 24]]\n",
    "\n",
    "print(x[:, :])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "print(x[::2, ::2])\n",
    "# [[11 13 15]\n",
    "#  [21 23 25]\n",
    "#  [31 33 35]]\n",
    "\n",
    "print(x[::-1, :])\n",
    "# [[31 32 33 34 35]\n",
    "#  [26 27 28 29 30]\n",
    "#  [21 22 23 24 25]\n",
    "#  [16 17 18 19 20]\n",
    "#  [11 12 13 14 15]]\n",
    "\n",
    "print(x[:, ::-1])\n",
    "# [[15 14 13 12 11]\n",
    "#  [20 19 18 17 16]\n",
    "#  [25 24 23 22 21]\n",
    "#  [30 29 28 27 26]\n",
    "#  [35 34 33 32 31]]\n",
    "```\n",
    "\n",
    "\n",
    "通过对每个以逗号分隔的维度执行单独的切片，你可以对多维数组进行切片。因此，对于二维数组，我们的第一片定义了行的切片，第二片定义了列的切片。\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "print(x)\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "x[0::2, 1::3] = 0\n",
    "print(x)\n",
    "# [[11  0 13 14  0]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21  0 23 24  0]\n",
    "#  [26 27 28 29 30]\n",
    "#  [31  0 33 34  0]]\n",
    "```\n",
    "\n",
    "## dots 索引\n",
    "\n",
    "NumPy 允许使用`...`表示足够多的冒号来构建完整的索引列表。\n",
    "\n",
    "比如，如果 `x` 是 5 维数组：\n",
    "\n",
    "- `x[1,2,...]` 等于 `x[1,2,:,:,:]`\n",
    "- `x[...,3]` 等于 `x[:,:,:,:,3]` \n",
    "- `x[4,...,5,:]` 等于 `x[4,:,:,5,:]`\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.random.randint(1, 100, [2, 2, 3])\n",
    "print(x)\n",
    "# [[[ 5 64 75]\n",
    "#   [57 27 31]]\n",
    "# \n",
    "#  [[68 85  3]\n",
    "#   [93 26 25]]]\n",
    "\n",
    "print(x[1, ...])\n",
    "# [[68 85  3]\n",
    "#  [93 26 25]]\n",
    "\n",
    "print(x[..., 2])\n",
    "# [[75 31]\n",
    "#  [ 3 25]]\n",
    "```\n",
    "\n",
    "\n",
    "\n",
    "## 整数数组索引\n",
    "\n",
    "【例】方括号内传入多个索引值，可以同时选择多个元素。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "r = [0, 1, 2]\n",
    "print(x[r])\n",
    "# [1 2 3]\n",
    "\n",
    "r = [0, 1, -1]\n",
    "print(x[r])\n",
    "# [1 2 8]\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "\n",
    "r = [0, 1, 2]\n",
    "print(x[r])\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]]\n",
    "\n",
    "r = [0, 1, -1]\n",
    "print(x[r])\n",
    "\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "r = [0, 1, 2]\n",
    "c = [2, 3, 4]\n",
    "y = x[r, c]\n",
    "print(y)\n",
    "# [13 19 25]\n",
    "```\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "r = np.array([[0, 1], [3, 4]])\n",
    "print(x[r])\n",
    "# [[1 2]\n",
    "#  [4 5]]\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "\n",
    "r = np.array([[0, 1], [3, 4]])\n",
    "print(x[r])\n",
    "# [[[11 12 13 14 15]\n",
    "#   [16 17 18 19 20]]\n",
    "#\n",
    "#  [[26 27 28 29 30]\n",
    "#   [31 32 33 34 35]]]\n",
    "\n",
    "# 获取了 5X5 数组中的四个角的元素。\n",
    "# 行索引是 [0,0] 和 [4,4]，而列索引是 [0,4] 和 [0,4]。\n",
    "r = np.array([[0, 0], [4, 4]])\n",
    "c = np.array([[0, 4], [0, 4]])\n",
    "y = x[r, c]\n",
    "print(y)\n",
    "# [[11 15]\n",
    "#  [31 35]]\n",
    "```\n",
    "\n",
    "【例】可以借助切片`:`与整数数组组合。\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "\n",
    "y = x[0:3, [1, 2, 2]]\n",
    "print(y)\n",
    "# [[12 13 13]\n",
    "#  [17 18 18]\n",
    "#  [22 23 23]]\n",
    "```\n",
    "\n",
    "- `numpy. take(a, indices, axis=None, out=None, mode='raise')` Take elements from an array along an axis.\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "r = [0, 1, 2]\n",
    "print(np.take(x, r))\n",
    "# [1 2 3]\n",
    "\n",
    "r = [0, 1, -1]\n",
    "print(np.take(x, r))\n",
    "# [1 2 8]\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "\n",
    "r = [0, 1, 2]\n",
    "print(np.take(x, r, axis=0))\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [21 22 23 24 25]]\n",
    "\n",
    "r = [0, 1, -1]\n",
    "print(np.take(x, r, axis=0))\n",
    "# [[11 12 13 14 15]\n",
    "#  [16 17 18 19 20]\n",
    "#  [31 32 33 34 35]]\n",
    "\n",
    "r = [0, 1, 2]\n",
    "c = [2, 3, 4]\n",
    "y = np.take(x, [r, c])\n",
    "print(y)\n",
    "# [[11 12 13]\n",
    "#  [13 14 15]]\n",
    "```\n",
    "\n",
    "应注意：使用切片索引到numpy数组时，生成的数组视图将始终是原始数组的子数组,\n",
    "        但是整数数组索引，不是其子数组，是形成新的数组。\n",
    "切片索引\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "a=np.array([[1,2],[3,4],[5,6]])\n",
    "b=a[0:1,0:1]\n",
    "b[0,0]=2\n",
    "print(a[0,0]==b)\n",
    "#[[True]]\n",
    "```\n",
    "整数数组索引\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "a=np.array([[1,2],[3,4],[5,6]])\n",
    "b=a[0,0]\n",
    "b=2\n",
    "print(a[0,0]==b)\n",
    "#False\n",
    "```\n",
    "\n",
    "## 布尔索引\n",
    "\n",
    "我们可以通过一个布尔数组来索引目标数组。\n",
    "\n",
    "【例】\n",
    "\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "y = x > 5\n",
    "print(y)\n",
    "# [False False False False False  True  True  True]\n",
    "print(x[x > 5])\n",
    "# [6 7 8]\n",
    "\n",
    "x = np.array([np.nan, 1, 2, np.nan, 3, 4, 5])\n",
    "y = np.logical_not(np.isnan(x))\n",
    "print(x[y])\n",
    "# [1. 2. 3. 4. 5.]\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "y = x > 25\n",
    "print(y)\n",
    "# [[False False False False False]\n",
    "#  [False False False False False]\n",
    "#  [False False False False False]\n",
    "#  [ True  True  True  True  True]\n",
    "#  [ True  True  True  True  True]]\n",
    "print(x[x > 25])\n",
    "# [26 27 28 29 30 31 32 33 34 35]\n",
    "```\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "x = np.linspace(0, 2 * np.pi, 50)\n",
    "y = np.sin(x)\n",
    "print(len(x))  # 50\n",
    "plt.plot(x, y)\n",
    "\n",
    "mask = y >= 0\n",
    "print(len(x[mask]))  # 25\n",
    "print(mask)\n",
    "'''\n",
    "[ True  True  True  True  True  True  True  True  True  True  True  True\n",
    "  True  True  True  True  True  True  True  True  True  True  True  True\n",
    "  True False False False False False False False False False False False\n",
    " False False False False False False False False False False False False\n",
    " False False]\n",
    "'''\n",
    "plt.plot(x[mask], y[mask], 'bo')\n",
    "\n",
    "mask = np.logical_and(y >= 0, x <= np.pi / 2)\n",
    "print(mask)\n",
    "'''\n",
    "[ True  True  True  True  True  True  True  True  True  True  True  True\n",
    "  True False False False False False False False False False False False\n",
    " False False False False False False False False False False False False\n",
    " False False False False False False False False False False False False\n",
    " False False]\n",
    "'''\n",
    "\n",
    "plt.plot(x[mask], y[mask], 'go')\n",
    "plt.show()\n",
    "```\n",
    "\n",
    "![](https://img-blog.csdnimg.cn/20191109183704335.png)\n",
    "\n",
    "我们利用这些条件来选择图上的不同点。蓝色点（在图中还包括绿点，但绿点掩盖了蓝色点），显示值 大于0 的所有点。绿色点表示值 大于0 且 小于0.5π 的所有点。\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "---\n",
    "# 数组迭代\n",
    "\n",
    "除了for循环，Numpy 还提供另外一种更为优雅的遍历方法。\n",
    "\n",
    "- `apply_along_axis(func1d, axis, arr)` Apply a function to 1-D slices along the given axis.\n",
    "\n",
    "【例】\n",
    "```python\n",
    "import numpy as np\n",
    "\n",
    "x = np.array([[11, 12, 13, 14, 15],\n",
    "              [16, 17, 18, 19, 20],\n",
    "              [21, 22, 23, 24, 25],\n",
    "              [26, 27, 28, 29, 30],\n",
    "              [31, 32, 33, 34, 35]])\n",
    "\n",
    "y = np.apply_along_axis(np.sum, 0, x)\n",
    "print(y)  # [105 110 115 120 125]\n",
    "y = np.apply_along_axis(np.sum, 1, x)\n",
    "print(y)  # [ 65  90 115 140 165]\n",
    "\n",
    "y = np.apply_along_axis(np.mean, 0, x)\n",
    "print(y)  # [21. 22. 23. 24. 25.]\n",
    "y = np.apply_along_axis(np.mean, 1, x)\n",
    "print(y)  # [13. 18. 23. 28. 33.]\n",
    "\n",
    "\n",
    "def my_func(x):\n",
    "    return (x[0] + x[-1]) * 0.5\n",
    "\n",
    "\n",
    "y = np.apply_along_axis(my_func, 0, x)\n",
    "print(y)  # [21. 22. 23. 24. 25.]\n",
    "y = np.apply_along_axis(my_func, 1, x)\n",
    "print(y)  # [13. 18. 23. 28. 33.]\n",
    "```\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "307.2px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
